package com.ztf.sm;

import com.ztf.sm.util.SM2KeyPair;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.FixedSecureRandom;

import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * @projectName: javabase
 * @package: com.ztf.sm
 * @className: TestMain
 * @author: kevin
 * @description: TODO
 * @date: 2022/4/14 0014 10:43
 * @version: 1.0
 */
public class TestMain {
    public static void main(String[] args)  {
        TestMain main = new TestMain();
        main.testString();
//        try {
//            main.generateKeyPair();

//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        }
    }

    public SM2KeyPair generateKeyPair()throws NoSuchAlgorithmException{

        //生成密钥对
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
        ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
        keyPairGenerator.init(new ECKeyGenerationParameters(domainParameters, SecureRandom.getInstance("SHA1PRNG")));
        AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();

        //私钥，16进制格式，自己保存，格式如a2081b5b81fbea0b6b973a3ab6dbbbc65b1164488bf22d8ae2ff0b8260f64853
        BigInteger privatekey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();
        String privateKeyHex = privatekey.toString(16);
        System.out.println("privateKeyHex="+privateKeyHex);
        //公钥，16进制格式，发给前端，格式如04813d4d97ad31bd9d18d785f337f683233099d5abed09cb397152d50ac28cc0ba43711960e811d90453db5f5a9518d660858a8d0c57e359a8bf83427760ebcbba
        ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();
        String publicKeyHex = Hex.toHexString(ecPoint.getEncoded(false));
        System.out.println("publicKeyHex="+publicKeyHex);
        SM2KeyPair sm2KeyPair = new SM2KeyPair(publicKeyHex,privateKeyHex);
        return sm2KeyPair;
    }


    public String testString(){
        //JS加密产生的密文
        String cipherData = "3070022100FCFD205CC084672B579B0117FD4318586F65E8FAF9CE1B7BF9F1F8035E6B6F7B022100CA4B6D45B93CE3FC9F9B973DF1C5990AEB0E1D67B6259495D7E50EE441122CBC04203D81BC75356E03C941A771DA7A76BD0073EC65249FAE37E55FD60F253E5AE4F0040655363606E81C";
        byte[] cipherDataByte = Hex.decode(cipherData);

        //刚才的私钥Hex，先还原私钥
        String privateKey = "F66C7379B663411008C6E6020FC44CD7731BCDA4294F810C27E4F7931563F19F";
        BigInteger privateKeyD = new BigInteger(privateKey, 16);
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());

        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters);

        //用私钥解密
        SM2Engine sm2Engine = new SM2Engine();
        sm2Engine.init(false, privateKeyParameters);

        //processBlock得到Base64格式，记得解码
        byte[] arrayOfBytes = new byte[0];
        try {
            arrayOfBytes = Base64.getDecoder().decode(sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length));
        } catch (InvalidCipherTextException e) {
            e.printStackTrace();
        }

        //得到明文：SM2 Encryption Test
        String data = new String(arrayOfBytes);
        return data;
    }

}
